use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::Instruction, rtda::Frame};


// Remainder double
#[derive(Debug, Default)]
pub struct DREM {}

impl Instruction for DREM {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_double();
        let v1 = stack.borrow_mut().pop_double();
        let result = v1 % v2;
        stack.borrow_mut().push_double(result);
    }
}

// Remainder float
#[derive(Debug, Default)]
pub struct FREM {}

impl Instruction for FREM {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_float();
        let v1 = stack.borrow_mut().pop_float();
        let result = v1 % v2;
        stack.borrow_mut().push_float(result);
    }
}


// Remainder int
#[derive(Debug, Default)]
pub struct IREM {}

impl Instruction for IREM {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_int();
        let v1 = stack.borrow_mut().pop_int();
        if v2 == 0 {
            panic!("java.lang.ArithmeticException: / by zero")
        }

        let result = v1 % v2;
        stack.borrow_mut().push_int(result);
    }
}

// Remainder long
#[derive(Debug, Default)]
pub struct LREM {}

impl Instruction for LREM {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let v2 = stack.borrow_mut().pop_long();
        let v1 = stack.borrow_mut().pop_long();
        if v2 == 0 {
            panic!("java.lang.ArithmeticException: / by zero")
        }

        let result = v1 % v2;
        stack.borrow_mut().push_long(result);
    }
}